package wci.frontend.pascal;

import wci.frontend.*;
import wci.frontend.pascal.tokens.PascalErrorToken;
import wci.frontend.pascal.tokens.PascalNumberToken;
import wci.frontend.pascal.tokens.PascalSpecialSymbolToken;
import wci.frontend.pascal.tokens.PascalStringToken;
import wci.frontend.pascal.tokens.PascalWordToken;
import static wci.frontend.Source.EOF;

/**
 * <h1>PascalScanner</h1>
 *
 * <p>用于Pascal源程序的Scanner</p>
 *
 * <p>Copyright (c) 2009 by Ronald Mak</p>
 * <p>For instructional purposes only.  No warranties.</p>
 */
public class PascalScanner extends Scanner
{
   
    public PascalScanner(Source source)
    {
        super(source);
    }

    /**
     * 提取source下一个Pascal Token。
     * @return token
     * @throws Exception.
     */
    protected Token extractToken()
        throws Exception
    {
    	skipWhiteSpace();
        Token token = null;
        char currentChar = currentChar();

        //文件结束，返回一个特殊EofToken
        if (currentChar == EOF) {
            token = new EofToken(source);
        }
        else if (Character.isLetter(currentChar)){//ID
        	token = new PascalWordToken(source);
        }else if (Character.isDigit(currentChar)){//数字
        	token = new PascalNumberToken(source);
        }else if (currentChar == '\''){ //字符串开头
        	token = new PascalStringToken(source);
        }else if (PascalTokenType.SPECIAL_SYMBOLS.containsKey(Character.toString(currentChar))){
        	token = new PascalSpecialSymbolToken(source);
        }
        else {
        	//不识别的token字符
        	token = new PascalErrorToken(source, PascalErrorCode.INVALID_CHARACTER, Character.toString(currentChar));
        	nextChar(); //跳到下一个字符
        }

        return token;
    }
    /**
     * <p>
     * 不处理空白，空白在一般语言都没啥意义，除了一些变态的比如Python语言之外<br>
     * 不过这里把注释当做空白，有点怪，一般是分别处理。
     * </p>
     */
	protected void skipWhiteSpace() throws Exception {
		char currentChar = currentChar();
		while (Character.isWhitespace(currentChar) || (currentChar == '{')) {
			 
            //是否一个注释头？
            if (currentChar == '{') {
                do {
                    currentChar = nextChar();
                } while ((currentChar != '}') && (currentChar != EOF));
 
                //找到注释尾
                if (currentChar == '}') {
                    currentChar = nextChar();  
                }
            }else {//正常的空白如  ' ', '\n', '\t'等，直接抛弃。
                currentChar = nextChar();  
            }
		}
	}
}
